package com.jl.js.process.command;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintStream;

import org.mozilla.javascript.Context;
import org.mozilla.javascript.Function;
import org.mozilla.javascript.Script;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.xml.XMLObject;

import com.jl.js.console.ConsoleShell;
import com.jl.js.console.IConsole;
import com.jl.js.console.LifeCycle;
import com.jl.process.util.ExceptionTools;

public class ScriptCommand implements ICommand {

	private IConsole console;
	private String cmd;
	private Context cx;

	private final static char next = ':';

	public ScriptCommand(IConsole console, String cmd) {
		this.console = console;
		this.cmd = cmd;
		cx = Context.getCurrentContext();
		makeCompilableUnit();
	}

	private void makeCompilableUnit() {
		PrintStream ps = console.getOut();
		BufferedReader br = console.getIn();

		while (!cx.stringIsCompilableUnit(cmd)) {
			ps.print(next);
			cmd += '\n';
			try {
				cmd += br.readLine();
			} catch (IOException e) {
				ExceptionTools.printRhinoExceptionMessage((ConsoleShell) console,e, console.getErr());
				console.setState(LifeCycle.QUIT);
				return;
			}
		}
	}

	@Override
	public void execute() {
		Scriptable scope = console.getScope();
		Script script = cx.compileString(cmd, "console", 1, null);
		Object result = script.exec(cx, scope);
		if ((result instanceof Function) && !(result instanceof XMLObject)) {
			Function fo = (Function) result;
			Object lastresult = scope.get("lastresult", scope);
			if (lastresult != null) {
				Object args[] = { lastresult };
				result = fo.call(cx, scope, scope, args);
			} else {
				Object args[] = {};
				result = fo.call(cx, scope, scope, args);
			}
		}
		console.refresh(result);
	}

	@Override
	public String toString() {
		return cmd;
	}

}
